package common

import (
	"bufio"
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"log"
	"os"
	"regexp"
	"strings"
)

var DB *sql.DB
var err error

type condition uint8

type User struct {
	Name     string    //用户名
	Pwd      string    //密码
	IsOnline condition //在线状态
}

func InitDB() (*sql.DB, error) {
	dsn := "root:123456@tcp(127.0.0.1:3306)/sql_test?charset=utf8mb4&parseTime=True"

	DB, err := sql.Open("mysql", dsn)
	fmt.Printf("%v", DB)
	if err != nil {
		return nil, err
	}
	//尝试与数据库建立连接（校验 dsn 是否正确）
	err = DB.Ping()
	if err != nil {
		return nil, err
	}
	return DB, nil
}

func Register(DB *sql.DB) (*User, bool) {
	fmt.Println("请输入用户名（\\q退出）：")
	reader := bufio.NewReader(os.Stdin)
	name, password := "", ""
	count := 0
	for count < 3 {
		if count == 3 {
			log.Println("注册失败。。。")
			return nil, false
		}
		buf := make([]byte, 1024)
		n, err := reader.Read(buf)
		name = strings.Trim(string(buf[:n]), "\r\n")
		if err != nil {
			log.Println(err)
			return nil, false
		}
		if name == "\\q" {
			return nil, false
		}
		if !CheckNameAndPassword(n, name) {
			log.Println("用户名格式有误，请重新输入：")
			count++
			continue
		}
		if _, i := QueryName(DB, name); i {
			log.Println("该用户名已存在，请重新输入：")
			count++
			continue
		} else {
			break
		}
	}
	fmt.Println("请输入密码：")
	for {
		buf := make([]byte, 1024)
		n, err := reader.Read(buf)
		if err != nil {
			log.Println(err)
			return nil, false
		}
		password = strings.Trim(string(buf[:n]), "\r\n")
		if !CheckNameAndPassword(n, password) || n < 8 {
			log.Println("密码格式有误，请重新输入：")
			continue
		} else {
			break
		}
	}
	if insertUser(DB, name, password) {
		u := &User{Name: name, Pwd: password}
		fmt.Println("注册成功！")
		//广播
		return u, true
	}
	return nil, false
}

func CheckNameAndPassword(n int, s string) bool {
	if n > 20 {
		return false
	}
	regex := regexp.MustCompile(`[\/\\,+><=^*@()|]`)
	if regex.MatchString(s) {
		return false
	} else {
		return true
	}
}

func QueryName(DB *sql.DB, name string) (*User, bool) {
	sqlStr := "select Name, Pwd, IsOnline from user where Name=?"
	u := &User{"", "", 1}
	rowObj := DB.QueryRow(sqlStr, name)
	err = rowObj.Scan(&u.Name, &u.Pwd, &u.IsOnline)
	if err != nil {
		if err == sql.ErrNoRows {
			return u, false
		}
		log.Println(err)
		return u, false
	}

	return u, true
}

func insertUser(DB *sql.DB, name, pwd string) bool {
	sqlStr := "insert into user(Name, Pwd) values (?,?)"
	_, err = DB.Exec(sqlStr, name, pwd)
	if err != nil {
		log.Println(err)
		return false
	}
	return true
}

func UpdateUser(DB *sql.DB, u *User, new string, condition string) {
	sqlStr := ""
	if condition == "\\rN" {
		sqlStr = "update user set Name=? where Name=?"
	} else {
		sqlStr = "update user set Pwd=? where Name=?"
	}
	_, err = DB.Exec(sqlStr, new, u.Name)
	if err != nil {
		log.Println(err)
		fmt.Println("修改失败！")
		return
	}
	fmt.Println("修改成功！")
	if u, ok := QueryName(DB, u.Name); ok {
		fmt.Println(u.Name, u.Pwd)
	} else {
		fmt.Println("不存在")
	}
}

func UpdateOnline(DB *sql.DB, u *User, isonline int) {
	sqlStr := "update user set IsOnline=? where Name=?"
	_, err = DB.Exec(sqlStr, isonline, u.Name)
	if err != nil {
		log.Println(err)
		return
	}
}
